/*****************************************************************************/
/**
 *  @file   SPHFileListToAVSField.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "SPHFileListToAVSField.h"
#include <kvs/Math>
#include <kvs/Vector3>
#include <kvs/ValueArray>
#include "SPHFileList.h"


namespace kvsbloodvis
{

namespace util
{

/*===========================================================================*/
/**
 *  @brief  Returns AVS field data as unchar-type regular grid in range of 0 to 255.
 *  @param  sph_list [in] SPH file list
 *  @return AVS field data
 */
/*===========================================================================*/
kvs::AVSField SPHFileListToAVSField( const SPHFileList& sph_list )
{
    const kvs::Vector3d global_org = sph_list.org();
    const kvs::Vector3d global_pitch = sph_list.pitch();
    const kvs::Vector3d global_max = sph_list.max();
    const kvs::Vector3ui resolution = sph_list.resolution();
    const kvs::UInt32 values_size = resolution.x() * resolution.y() *resolution.z();
    kvs::ValueArray<kvs::UInt8> values( values_size );
    for ( size_t index = 0; index < sph_list.size(); index++ )
    {
        const kvs::Vector3d local_max = sph_list.sph( index ).max();
        const kvs::Vector3d local_org = sph_list.sph( index ).org();
        const kvs::Vector3d local_pitch = sph_list.sph( index ).pitch();
        const kvs::AnyValueArray local_data = sph_list.sph( index ).data();
        const size_t I_start = ( local_org[0] - global_org[0] ) / global_pitch[0];
        const size_t J_start = ( local_org[1] - global_org[1] ) / global_pitch[1];
        const size_t K_start = ( local_org[2] - global_org[2] ) / global_pitch[2];
        const size_t i_end = local_max[0];
        const size_t j_end = local_max[1];
        const size_t k_end = local_max[2];
        for ( size_t k = 0, K = K_start; k < k_end; k++, K++ )
        {
            for ( size_t j = 0, J = J_start; j < j_end; j++, J++ )
            {
                for ( size_t i = 0, I = I_start; i < i_end; i++, I++ )
                {
                    const size_t local_index = k * local_max[0] * local_max[1] + j * local_max[0] + i;
                    const size_t global_index = K * global_max[0] * global_max[1] + J * global_max[0] + I;
                    kvs::Real64 value = kvs::Math::Clamp( local_data.at<kvs::Real64>( local_index ), 0.0, 1.0 );
                    values[ global_index ] = kvs::Math::Round( 255.0 * value );
                }
            }
        }
    }

    kvs::AVSField avs;
    avs.setBits( 8 );
    avs.setSigned( false );
    avs.setVeclen( 1 );
    avs.setNSpace( 3 );
    avs.setNDim( 3 );
    avs.setDim( resolution );
    avs.setFieldType( kvs::AVSField::Uniform );
    avs.setDataType( kvs::AVSField::Byte );
    avs.setValues( values );

    return avs;
}

} // end of namespace util

} // end of namespace kvsbloodvis
